package com.jihox.abookpro;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.jihox.abookpro.R;
import com.jihox.abookpro.helper.MailSendHelp;
import com.jihox.abookpro.util.ConfigProperties;
import com.jihox.abookpro.util.MailSenderInfo;

/**
 * 
 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
 * 
 * */
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
	public static final String TAG = "CrashHandler";
	//用户订单时的sp名称
	public static final String PREFS_NAME = "DeliveryInfoPrefsFile1";
	// 系统默认的UncaughtException处理类
	private Thread.UncaughtExceptionHandler mDefaultHandler;
	// CrashHandler实例
	private static MyUncaughtExceptionHandler INSTANCE = new MyUncaughtExceptionHandler();
	// 程序的Context对象
	private Context mContext;
	// 用来存储设备信息和异常信息
	private Map<String, String> infos = new HashMap<String, String>();
	
	// 用户的查询邮箱
	private String UserEmail=null;
	private StringBuffer Version=new StringBuffer();
	//邮箱设置信息
	private String ErrorEmail=ConfigProperties.getErrorMail();
	private String ReceiveEmail=ConfigProperties.getErrorMailReciver();
	private String pwd=ConfigProperties.getErrorMailPwd();
	private String host=ConfigProperties.getMailHost();

	/**
	 * 保证只有一个UncaughtException实例
	 */
	private MyUncaughtExceptionHandler() {
		
	}
	/** 获取UncaughtException实例 ,单例模式 */
	public static MyUncaughtExceptionHandler getInstance() {
		return INSTANCE;
	}
	/** * 初始化 * * @param context */
	public void init(Context context) {
		mContext = context;
		// 获取系统默认的UncaughtException处理器
		mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
		// 设置该CrashHandler为程序的默认处理器
		Thread.setDefaultUncaughtExceptionHandler(this);
	}
	/**
	 * 
	 * 当UncaughtException发生时会转入该函数来处理
	 */
	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		
		if (!handleException(ex) && mDefaultHandler != null) {
			// 如果用户没有处理则让系统默认的异常处理器来处理
			mDefaultHandler.uncaughtException(thread, ex);
		}
		else {
			try {
				Thread.sleep(4000);
			}

			catch (InterruptedException e) {
				Log.e(TAG, "error : ", e);
			}
			// 退出程序
			//Log.d(TAG,"exit");
			android.os.Process.killProcess(android.os.Process.myPid());
			System.exit(10);
		}
	}

	/**
	 * 
	 * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
	 * @param ex
	 * @return true:如果处理了该异常信息;否则返回false.
	 */

	private boolean handleException(final Throwable ex) {
		if (ex == null || !MyApplication.getInstance().isSendErrorMail()) {
			return true;
		}
		// 使用Toast来显示异常信息
		new Thread() {

			@Override
			public void run() {
				Looper.prepare();
				Toast.makeText(mContext, mContext.getResources().getString(R.string.T_Uncaught_message), Toast.LENGTH_LONG)
						.show();
				Looper.loop();
			}
		}.start();
		// 收集设备参数信息
		collectDeviceInfo(mContext);
		collectUserInfo();
		//发送错误信息
		SendExceptionByEmail(ex);
		return true;
	}

	/**
	 * 收集设备参数信息
	 * 
	 * @param ctx
	 */

	public void collectDeviceInfo(Context ctx) {
		try {
			PackageManager pm = ctx.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
					PackageManager.GET_ACTIVITIES);
			if (pi != null) {
				String versionName = pi.versionName == null ? "null"
						: pi.versionName;
				String versionCode = pi.versionCode + "";
				Version.append("VersionName= ");
				Version.append(versionName);
				Version.append("\n");
				Version.append("VersionCode= ");
				Version.append(versionCode);
				Version.append("\n");
			}
		} catch (NameNotFoundException e) {
			Log.e(TAG, "an error occured when collect package info", e);
		}
		Field[] fields = Build.class.getDeclaredFields();
		for (Field field : fields) {
			try {
				field.setAccessible(true);
				infos.put(field.getName(), field.get(null).toString());
			} catch (Exception e) {
				Log.e(TAG, "an error occured when collect crash info", e);
			}
		}
		
	}
	
	public void collectUserInfo()
	{
		//获取用户订单时的Email
		SharedPreferences sp = mContext.getSharedPreferences(PREFS_NAME, mContext.MODE_PRIVATE);
		UserEmail = sp.getString("Email", "");
	}
	
	/**
	 * 能过邮件发送错误信息
	 * @param ex
	 * @return
	 */
	private boolean SendExceptionByEmail(Throwable ex)
	{
		//收集信息
		StringBuffer sb=new StringBuffer();
		
		//添加UserEmail 
		sb.append("UserEmail= "+UserEmail+"\n");
		
		//邮件的subject 
		String subject=null;
		for(Map.Entry<String, String> entry : infos.entrySet())
		{
			String key = entry.getKey();
			String value = entry.getValue();
			sb.append(key+"=" +value+"\n");
		}
		Writer writer = new StringWriter();
		PrintWriter printWriter = new PrintWriter(writer);
		ex.printStackTrace(printWriter);
		Throwable cause = ex.getCause();
		while(cause != null)
		{
			cause.printStackTrace(printWriter);
			cause=cause.getCause();
		}
		printWriter.close();
		String result= writer.toString();
		Log.e(TAG,result);
		//查找第一个发现com.jihox.abookpro的单词
		for(String ClassName: result.split("[ $():]")){
			if(ClassName.startsWith(mContext.getPackageName())){
				subject=ClassName;
				break;
			}
		}
		subject="Android_"+mContext.getResources().getString(R.string.app_name) + "_" + subject;
		sb.append("\n");
		sb.append(result);
		//通过邮件发送信息
		AsyncTask<String, Integer, Boolean> sendTask= new AsyncTask<String, Integer, Boolean>(){
			@Override
			protected Boolean doInBackground(java.lang.String... content) {
				// TODO Auto-generated method stub
				try{
					MailSenderInfo mailInfo=new MailSenderInfo();
					mailInfo.setMailServerHost(host);
					mailInfo.setMailServerPort("25");
					mailInfo.setValidate(true);
					mailInfo.setUserName(ErrorEmail);
					mailInfo.setPassword(pwd);
					mailInfo.setFromAddress(ErrorEmail);
					mailInfo.setToAddress(ReceiveEmail);
					mailInfo.setSubject(content[1]);
					mailInfo.setContent(content[0]);
					MailSendHelp sms = new MailSendHelp();   
			        boolean result=sms.sendTextMail(mailInfo);
			        return result;
					}
					catch(Exception e)
					{
						e.printStackTrace();
						return false;
					}				
			}			
			@Override
			protected void onPostExecute(Boolean result)
			{
				return;
			}	
		};
		//第一个参数是内容，第二个参数是subject
		sendTask.execute(Version.toString()+"\n"+sb.toString(),subject);
		MyApplication.getInstance().setSendErrorMail(false);
		return true;
	}

	/**
	 * 能过邮件发送错误信息
	 * @param ex
	 * @return
	 */
	public boolean SendExceptionByEmail(Throwable ex,String subject)
	{
		// 收集设备参数信息
		collectDeviceInfo(mContext);
		collectUserInfo();
		//收集信息
		StringBuffer sb=new StringBuffer();
		
		//添加UserEmail 
		sb.append("UserEmail= "+UserEmail+"\n");
		
		for(Map.Entry<String, String> entry : infos.entrySet())
		{
			String key = entry.getKey();
			String value = entry.getValue();
			sb.append(key+"=" +value+"\n");
		}
		Writer writer = new StringWriter();
		PrintWriter printWriter = new PrintWriter(writer);
		ex.printStackTrace(printWriter);
		Throwable cause = ex.getCause();
		while(cause != null)
		{
			cause.printStackTrace(printWriter);
			cause=cause.getCause();
		}
		printWriter.close();
		String result= writer.toString();
		Log.e(TAG,result);
		//查找第一个发现com.jihox.abookpro的单词
		for(String ClassName: result.split("[ $():]")){
			if(ClassName.startsWith(mContext.getPackageName())){
				subject=subject + ClassName;
				break;
			}
		}
		subject="Android_"+mContext.getResources().getString(R.string.app_name) + "_" + subject;
		sb.append("\n");
		sb.append(result);
		//通过邮件发送信息
		AsyncTask<String, Integer, Boolean> sendTask= new AsyncTask<String, Integer, Boolean>(){
			@Override
			protected Boolean doInBackground(java.lang.String... content) {
				// TODO Auto-generated method stub
				try{
					MailSenderInfo mailInfo=new MailSenderInfo();
					mailInfo.setMailServerHost(host);
					mailInfo.setMailServerPort("25");
					mailInfo.setValidate(true);
					mailInfo.setUserName(ErrorEmail);
					mailInfo.setPassword(pwd);
					mailInfo.setFromAddress(ErrorEmail);
					mailInfo.setToAddress(ReceiveEmail);
					mailInfo.setSubject(content[1]);
					mailInfo.setContent(content[0]);
					MailSendHelp sms = new MailSendHelp();   
			        boolean result=sms.sendTextMail(mailInfo);
			        return result;
					}
					catch(Exception e)
					{
						e.printStackTrace();
						return false;
					}				
			}			
			@Override
			protected void onPostExecute(Boolean result)
			{
				return;
			}	
		};
		//第一个参数是内容，第二个参数是subject
		sendTask.execute(Version.toString()+"\n"+sb.toString(),subject);
		MyApplication.getInstance().setSendErrorMail(false);
		return true;
	}
}
